<template>
  <div class="draggable-sider" :class="{ toggled, right: side === 'right' }" :style="{ minWidth: calcMinWidth + 'px', maxWidth: maxWidth + 'px', width: width + 'px' }">
    <div class="draggable-sider__content" v-show="!toggled">
      <slot name="content"></slot>
    </div>
    <div
      id="dragHandler"
      v-show="!toggled"
      class="border-handler"
      :style="{ right: side === 'left' ? '-3px' : 'auto', left: side === 'right' ? '-3px' : 'auto' }"
      @mousedown.stop.prevent="onMouseDown"
    ></div>
    <sider-toggle slot="toggle" class="tree-toggle" :side="side" @click="onToggle" />
  </div>
</template>

<script>
let currentX = 0;
let currentWidth = 0;
export default {
  name: 'DraggableSider',
  props: {
    minWidth: {
      type: String | Number,
      default: 250,
    },
    side: {
      type: String,
      default: 'left', // left right
    },
  },
  data() {
    return {
      toggled: false,
      dragging: false,
      calcMinWidth: 0,
      maxWidth: 'none',
      originWidth: 0, // 用于记录toggle前的width
      width: 0,
    };
  },

  created() {
    this.calcMinWidth = this.originWidth = this.width = typeof this.minWidth === 'string' ? parseInt(this.minWidth) : this.minWidth;
    this.maxWidth = Math.max(document.documentElement.clientWidth / 2, parseInt(this.minWidth));
  },

  mounted() {
    document.documentElement.addEventListener('mousemove', this.onMouseMove, true);
    document.documentElement.addEventListener('mouseup', this.onMouseUp, true);
  },
  beforeDestroy() {
    document.documentElement.removeEventListener('mousemove', this.onMouseMove);
    document.documentElement.removeEventListener('mouseup', this.onMouseUp);
  },

  methods: {
    onToggle() {
      this.toggled = !this.toggled;
      if (this.toggled) {
        this.width = 0;
        this.calcMinWidth = 0;
        this.maxWidth = 0;
      } else {
        this.width = this.originWidth;
        this.calcMinWidth = typeof this.minWidth === 'string' ? parseInt(this.minWidth) : this.minWidth;
        this.maxWidth = this.originWidth;
        setTimeout(() => {
          // 为了让展开和收起的速度一致，先把maxWidth放开到原宽度，过0.2s再设置为view的一半
          this.maxWidth = Math.max(document.documentElement.clientWidth / 2, parseInt(this.minWidth));
        }, 200);
      }
      this.$emit('toggle');
    },

    onMouseDown(e) {
      this.dragging = true;
      currentX = e.clientX;
      currentWidth = parseInt(this.width);
    },

    onMouseMove(e) {
      if (!this.dragging) return;
      const deltaX = e.clientX - currentX;
      let finalWidth = 0;
      if (this.side === 'left') {
        finalWidth = currentWidth + deltaX;
      } else if (this.side === 'right') {
        finalWidth = currentWidth - deltaX;
      }
      this.width = Math.max(finalWidth, parseInt(this.minWidth));
    },

    onMouseUp(e) {
      if (this.dragging) {
        this.dragging = false;
        this.originWidth = this.width;
      }
    },
  },
};
</script>

<style lang="less" scoped>
.draggable-sider {
  position: relative;
  height: 100%;
  box-shadow: 2px 4px 6px 0 #e4e4e4;
  transition: min-width 0.2s, max-width 0.2s;

  &__content {
    height: 100%;
    overflow-y: auto;
  }

  .border-handler {
    position: absolute;
    width: 6px;
    top: 0;
    bottom: 0;
    cursor: col-resize;
  }

  .tree-toggle {
    position: absolute;
    top: 50%;
    right: -20px;
    transform: translateY(-50px);
    opacity: 0;
    z-index: 999;
    transition: opacity 0.3s;
  }

  &:hover {
    .tree-toggle {
      opacity: 1;
    }
  }

  &.right {
    box-shadow: -2px 4px 6px 0 #e4e4e4;
    .tree-toggle {
      left: -20px;
      right: auto;
    }
  }

  &.toggled {
    .tree-toggle {
      opacity: 1;
    }
  }
}
</style>
